#!/usr/bin/env ruby

# -------------------------------------------------------------------------- #
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org)             #
#                                                                            #
# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
# not use this file except in compliance with the License. You may obtain    #
# a copy of the License at                                                   #
#                                                                            #
# http://www.apache.org/licenses/LICENSE-2.0                                 #
#                                                                            #
# Unless required by applicable law or agreed to in writing, software        #
# distributed under the License is distributed on an "AS IS" BASIS,          #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
# See the License for the specific language governing permissions and        #
# limitations under the License.                                             #
#--------------------------------------------------------------------------- #

ONE_LOCATION=ENV["ONE_LOCATION"]

if !ONE_LOCATION
    RUBY_LIB_LOCATION="/usr/lib/one/ruby"
else
    RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
end

$: << RUBY_LIB_LOCATION


require 'OpenNebula'
require 'client_utilities'
require 'command_parse'


ShowTableUP={
    :id => {
        :name => "ID",
        :desc => "ONE identifier for cluster",
        :size => 4,
        :proc => lambda {|d,e| 
            d.id 
        }
    },
    :name => {
        :name => "NAME",
        :desc => "Name of the cluster",
        :size => 8,
        :proc => lambda {|d,e|
            d.name
        }
    },
   
    :default => [:id, :name]
}

class UPShow
    def initialize
        @clusterpool=OpenNebula::ClusterPool.new(get_one_client)
        @table=ShowTable.new(ShowTableUP)
    end
    
    def header_up_small
        scr_bold
        scr_underline
        print @table.header_str
        scr_restore
        puts ""
    end
    
    def list_short(options=nil)
        res=@clusterpool.info
        if options
            @table.columns=options[:columns] if options[:columns]
        end

        if OpenNebula.is_error?(res)
            result=res
        else
            result=res
            header_up_small
            
            puts @table.data_str(@clusterpool, options)
            result
        end
    end
end

class OneUPParse < CommandParse
    
    COMMANDS_HELP=<<-EOT

Description:

This command enables the OpenNebula administrator to manage clusters. The
administrator can create, delete, as well as add and remove hosts from them.
Any user can list available clusters.


Commands:

* create (Creates a new cluster)
    onecluster create clustername
    
* delete (Removes a cluster)
    onecluster delete <id>
    
* list (Lists all the clusters in the pool)
    onecluster list

* addhost (Add a host to the cluster)
    onecluster addhost <host_id> <cluster_id>
        
* removehost (Remove a host from the cluster)
    onecluster removehost <host_id> <cluster_id>
    
EOT

    def text_commands
        COMMANDS_HELP
    end

    def text_command_name
        "onecluster"
    end

    def list_options
        table=ShowTable.new(ShowTableUP)
        table.print_help
    end

end

oneup_opts=OneUPParse.new([:list, :xml])
oneup_opts.parse(ARGV)
ops=oneup_opts.options

result=[false, "Unknown error"]

command=ARGV.shift

case command
when "create"
    check_parameters("create", 1)
    cluster=OpenNebula::Cluster.new(OpenNebula::Cluster.build_xml, get_one_client)
    result=cluster.allocate(ARGV[0])
    
    if is_successful?(result)
        puts "ID: " + cluster.id.to_s if ops[:verbose]
        exit 0
    end
    
when "delete"
    check_parameters("delete", 1)
    args=expand_args(ARGV)

    args.each do |param|
        cluster_id=get_cluster_id(param)
        cluster=OpenNebula::Cluster.new(
            OpenNebula::Cluster.build_xml(cluster_id), get_one_client)
        result=cluster.delete
        if !OpenNebula.is_error?(result)
            puts "Cluster deleted" if ops[:verbose]
            break
        end
    end

when "addhost"
    check_parameters("addhost", 2)
    cluster_id=get_cluster_id(ARGV[-1])
    cluster=OpenNebula::Cluster.new(
        OpenNebula::Cluster.build_xml(cluster_id), get_one_client)
    args=expand_args(ARGV[0..-2])

    args.each do |param|
        host_id=get_host_id(param)

        result=cluster.add_host(host_id)
        if is_successful?(result)
            puts "Added HOST to the Cluster" if ops[:verbose]
        else
            break
        end
    end
    
when "removehost"
    check_parameters("removehost", 2)
    cluster_id=get_cluster_id(ARGV[-1])
    cluster=OpenNebula::Cluster.new(
        OpenNebula::Cluster.build_xml(cluster_id), get_one_client)
    args=expand_args(ARGV[0..-2])

    args.each do |param|
        host_id=get_host_id(param)

        result=cluster.remove_host(host_id)
        if is_successful?(result)
            puts "Host removed from the Cluster" if ops[:verbose]
        else
            break
        end
    end
    
when "list"
    if !ops[:xml]
        uplist=UPShow.new
        ops[:columns]=ops[:list] if ops[:list]
        result=uplist.list_short(ops)
    else
        clusterpool=OpenNebula::ClusterPool.new(get_one_client)
        clusterpool.info
        puts clusterpool.to_xml(true)
    end
    
else
    oneup_opts.print_help
    exit -1
end

if OpenNebula.is_error?(result)
    puts "Error: " + result.message
    exit -1
end
